/***************************************************************************
 *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "pch.h"
# include <Inventor/draggers/SoTranslate2Dragger.h>


#include <App/Document.h>



#include "ViewProviderAnnotation.h"
#include "Gui/Application.h"

#include <App/Document.h>
#include "SoFCSelection.h"
#include "SoTextLabel.h"
#include "Tools.h"

#include <App/DocumentObject.h>
#include <Gui/Document.h>
using namespace Gui;

const char* ViewProviderAnnotation::JustificationEnums[]= {"Left","Right","Center",nullptr};
const char* ViewProviderAnnotation::RotationAxisEnums[]= {"X","Y","Z",nullptr};

TYPESYSTEM_SOURCE(Gui::ViewProviderAnnotation, Gui::ViewProviderDocumentObject)


ViewProviderAnnotation::ViewProviderAnnotation()
{
    
    unsigned long col = (4294967295UL); // light grey
    float r,g,b;
    r = ((col >> 24) & 0xff) / 255.0; g = ((col >> 16) & 0xff) / 255.0; b = ((col >> 8) & 0xff) / 255.0;
  

    pFont = new SoFont();
    pFont->ref();
    pLabel = new SoText2();
    pLabel->ref();
    pLabel3d = new SoAsciiText();
    pLabel3d->ref();
    pColor = new SoBaseColor();
    pColor->ref();
    pTranslation = new SoTranslation();
    pTranslation->ref();
    pRotationXYZ = new SoRotationXYZ();
    pRotationXYZ->ref();

    

    

    sPixmap = "Tree_Annotation";
}

ViewProviderAnnotation::~ViewProviderAnnotation()
{
    pFont->unref();
    pLabel->unref();
    pLabel3d->unref();
    pColor->unref();
    pTranslation->unref();
    pRotationXYZ->unref();
}



std::vector<std::string> ViewProviderAnnotation::getDisplayModes() const
{
    // add modes
    std::vector<std::string> StrList;
    StrList.push_back("Screen");
    StrList.push_back("World");
    return StrList;
}

void ViewProviderAnnotation::setDisplayMode(const char* ModeName)
{
    if (strcmp(ModeName, "Screen") == 0)
        setDisplayMaskMode("Screen");
    else if (strcmp(ModeName, "World")==0)
        setDisplayMaskMode("World");

    ViewProviderDocumentObject::setDisplayMode(ModeName);
}

void ViewProviderAnnotation::attach(App::DocumentObject* f)
{
    ViewProviderDocumentObject::attach(f);

    SoAnnotation* anno = new SoAnnotation();
    SoAnnotation* anno3d = new SoAnnotation();

    SoFCSelection* textsep = new SoFCSelection();

    // set selection/highlight colors
    float transparency;
    
    SbColor highlightColor = textsep->colorHighlight.getValue();
    unsigned long highlight = (unsigned long)(highlightColor.getPackedValue());
    
    highlightColor.setPackedValue((uint32_t)highlight, transparency);
    textsep->colorHighlight.setValue(highlightColor);
    // Do the same with the selection color
    SbColor selectionColor = textsep->colorSelection.getValue();
    unsigned long selection = (unsigned long)(selectionColor.getPackedValue());
    
    selectionColor.setPackedValue((uint32_t)selection, transparency);
    textsep->colorSelection.setValue(selectionColor);

    textsep->objectName = pcObject->getNameInDocument();
    textsep->documentName = pcObject->getDocument()->getName();
    textsep->subElementName = "Main";
    textsep->addChild(pTranslation);
    textsep->addChild(pRotationXYZ);
    textsep->addChild(pColor);
    textsep->addChild(pFont); // causes problems
    textsep->addChild(pLabel);

    SoFCSelection* textsep3d = new SoFCSelection();

    // set sel/highlight color here too
    textsep3d->colorHighlight.setValue(highlightColor);
    textsep3d->colorSelection.setValue(selectionColor);

    textsep3d->objectName = pcObject->getNameInDocument();
    textsep3d->documentName = pcObject->getDocument()->getName();
    textsep3d->subElementName = "Main";
    textsep3d->addChild(pTranslation);
    textsep3d->addChild(pRotationXYZ);
    textsep3d->addChild(pColor);
    textsep3d->addChild(pFont);
    textsep3d->addChild(pLabel3d);

    anno->addChild(textsep);
    anno3d->addChild(textsep3d);

    addDisplayMaskMode(anno, "Screen");
    addDisplayMaskMode(anno3d, "World");
}



// ----------------------------------------------------------------------------

const char* ViewProviderAnnotationLabel::JustificationEnums[]= {"Left","Right","Center",nullptr};

TYPESYSTEM_SOURCE(Gui::ViewProviderAnnotationLabel, Gui::ViewProviderDocumentObject)


ViewProviderAnnotationLabel::ViewProviderAnnotationLabel()
{

}

ViewProviderAnnotationLabel::~ViewProviderAnnotationLabel()
{
    pColor->unref();
    pBaseTranslation->unref();
    pTextTranslation->unref();
    pCoords->unref();
    pImage->unref();
}



std::vector<std::string> ViewProviderAnnotationLabel::getDisplayModes() const
{
    // add modes
    std::vector<std::string> StrList;
    StrList.push_back("Line");
    StrList.push_back("Object");
    return StrList;
}

void ViewProviderAnnotationLabel::setDisplayMode(const char* ModeName)
{
    if (strcmp(ModeName, "Line") == 0)
        setDisplayMaskMode("Line");
    else if (strcmp(ModeName, "Object")==0)
        setDisplayMaskMode("Object");

    ViewProviderDocumentObject::setDisplayMode(ModeName);
}

void ViewProviderAnnotationLabel::attach(App::DocumentObject* f)
{
    ViewProviderDocumentObject::attach(f);

    // plain image
    SoSeparator* textsep = new SoAnnotation();
    textsep->addChild(pBaseTranslation);
    textsep->addChild(pImage);

    // image with line
    SoSeparator* linesep = new SoAnnotation();
    linesep->addChild(pBaseTranslation);
    linesep->addChild(pColor);
    linesep->addChild(pCoords);
    linesep->addChild(new SoLineSet());
    SoDrawStyle *ds = new SoDrawStyle();
    ds->pointSize.setValue(3.0f);
    linesep->addChild(ds);
    linesep->addChild(new SoPointSet());
    linesep->addChild(pTextTranslation);
    linesep->addChild(pImage);

    addDisplayMaskMode(linesep, "Line");
    addDisplayMaskMode(textsep, "Object");
}


bool ViewProviderAnnotationLabel::doubleClicked()
{
    Gui::Application::Instance->activeDocument()->setEdit(this);
    return true;
}

void ViewProviderAnnotationLabel::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
    menu->addAction(QObject::tr("Move annotation"), receiver, member);
}

void ViewProviderAnnotationLabel::dragStartCallback(void *, SoDragger *)
{
    // This is called when a manipulator is about to manipulating
    Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Transform"));
}

void ViewProviderAnnotationLabel::dragFinishCallback(void *, SoDragger *)
{
    // This is called when a manipulator has done manipulating
    Gui::Application::Instance->activeDocument()->commitCommand();
}

void ViewProviderAnnotationLabel::dragMotionCallback(void *data, SoDragger *drag)
{
    ViewProviderAnnotationLabel* that = reinterpret_cast<ViewProviderAnnotationLabel*>(data);
    const SbMatrix& mat = drag->getMotionMatrix();
    App::DocumentObject* obj = that->getObject();

}

bool ViewProviderAnnotationLabel::setEdit(int ModNum)
{
    Q_UNUSED(ModNum);
    SoSearchAction sa;
    sa.setInterest(SoSearchAction::FIRST);
    sa.setSearchingAll(false);
    sa.setNode(this->pTextTranslation);
    sa.apply(pcRoot);
    SoPath * path = sa.getPath();
    if (path) {
        TranslateManip * manip = new TranslateManip;
        SoDragger* dragger = manip->getDragger();
        dragger->addStartCallback(dragStartCallback, this);
        dragger->addFinishCallback(dragFinishCallback, this);
        dragger->addMotionCallback(dragMotionCallback, this);
        return manip->replaceNode(path);
    }

    return false;
}

void ViewProviderAnnotationLabel::unsetEdit(int ModNum)
{
    Q_UNUSED(ModNum);
    SoSearchAction sa;
    sa.setType(TranslateManip::getClassTypeId());
    sa.setInterest(SoSearchAction::FIRST);
    sa.apply(pcRoot);
    SoPath * path = sa.getPath();

    // No transform manipulator found.
    if (!path)
        return;

    TranslateManip * manip = static_cast<TranslateManip*>(path->getTail());
    SoTransform* transform = this->pTextTranslation;
    manip->replaceManip(path, transform);
}

void ViewProviderAnnotationLabel::drawImage(const std::vector<std::string>& s){}
